/**
 * @author Nicolas Lusa (lusan@usi.ch)
 * @author Nicolas Zimerman (zimerman@usi.ch)
 */
package ch.usi.inf.pf2.gui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;
import javax.swing.ToolTipManager;

import ch.usi.inf.pf2.circuit.Component;
import ch.usi.inf.pf2.gui.tool.AndGateCreationTool;
import ch.usi.inf.pf2.gui.tool.InputCreationTool;
import ch.usi.inf.pf2.gui.tool.NandGateCreationTool;
import ch.usi.inf.pf2.gui.tool.NorGateCreationTool;
import ch.usi.inf.pf2.gui.tool.NotGateCreationTool;
import ch.usi.inf.pf2.gui.tool.OrGateCreationTool;
import ch.usi.inf.pf2.gui.tool.OutputCreationTool;
import ch.usi.inf.pf2.gui.tool.SelectionTool;
import ch.usi.inf.pf2.gui.tool.SetDelayTool;
import ch.usi.inf.pf2.gui.tool.Tool;
import ch.usi.inf.pf2.gui.tool.WaveformTool;
import ch.usi.inf.pf2.gui.tool.WireCreationTool;
import ch.usi.inf.pf2.gui.tool.XorGateCreationTool;

public final class CircuitArea extends JComponent implements
		MouseMotionListener {

	private static final long serialVersionUID = 2761081626901799514L;
	private final Model model;
    private Tool currentTool;
    private Tool[] tools;
    
    private int WIDTH = 3;
    private BasicStroke bs = new BasicStroke(WIDTH);
    
    public CircuitArea(final CircuitFrame circuitFrame, final Model model) {

		 setAutoscrolls(true); // enable synthetic drag events
		 addMouseMotionListener(this); // handle mouse drags
		 

        this.model = model;
        
        tools = new Tool[] {
            new SelectionTool(model),
            //new SetInputTool(circuitFrame, model),
            new WaveformTool(circuitFrame, model),
            new SetDelayTool(model),
            new WireCreationTool(model),
            new NotGateCreationTool(model), 
            new AndGateCreationTool(model),
            new OrGateCreationTool(model),
            new NandGateCreationTool(model),
            new NorGateCreationTool(model),
            new XorGateCreationTool(model),
            new InputCreationTool(model),
            new OutputCreationTool(model)
        };
        setCurrentTool(tools[0]);
        
        ToolTipManager.sharedInstance().registerComponent(this);
        
        // register listeners
        model.addCircuitListener(new CircuitListener() {
            public void circuitChanged() {
				setPreferredSize(new Dimension(model.getCircuit()
						.getFurtherstComponentPositionX() + 30, model
						.getCircuit().getFurtherstComponentPositionY() + 30));
				revalidate();
                repaint();
            }
        });
        model.addSelectionListener(new SelectionListener() {
            public void selectionChanged() {
                repaint();
            }
        });
        model.addComponentListener(new ComponentListener() {
            public void componentChanged() {
                repaint();
            }
        });
    }
    
    public Tool[] getTools() {
        return tools;
    }
    
    public Tool getCurrentTool() {
        return currentTool;
    }
    
    public void setCurrentTool(final Tool tool) {
        if (currentTool!=null) {
            removeMouseListener(currentTool);
            removeMouseMotionListener(currentTool);
            removeKeyListener(currentTool);
        }
        this.currentTool = tool;
        if (currentTool!=null) {
            addMouseListener(currentTool);
            addMouseMotionListener(currentTool);
            addKeyListener(currentTool);
        }
    }
    
    public String getToolTipText(final MouseEvent ev) {
        final int x = ev.getX();
        final int y = ev.getY();
        final Component shape = model.getCircuit().findShapeAt(x, y);
        return shape==null?null:"<html><b>"+shape.getClass().getName()+"</b><br>"+shape;
    }
    
    public void paintComponent(final Graphics g) {
    	Graphics2D g2 = (Graphics2D)g;
    	g2.setStroke(bs);
        g2.setColor(Color.WHITE);
        g2.fillRect(0, 0, getWidth(), getHeight());
        
        g2.setColor(Color.BLACK);
        for (final Component shape : model.getCircuit()) {
            if(shape.getColor().equals("green")) {
            	g2.setColor(new Color(0,210,0));
            } else if(shape.getColor().equals("blue")) {
            	g2.setColor(Color.BLUE);
            } else g2.setColor(Color.BLACK);
        	shape.draw(g2);
        }
        
        g2.setColor(Color.RED);
        for (final Component shape : model.getSelection()) {
            shape.draw(g2);
        }
    }

	@Override
	public void mouseDragged(MouseEvent e) {
		 Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
		 scrollRectToVisible(r);
		 repaint();
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
    
}